import React, { useEffect, useState } from 'react';
import * as d3 from 'd3';

// 定义接口类型
interface Node {
  id: number;
  label: string;
  type: string;
  x?: number;
  y?: number;
}

interface Edge {
  source: number | Node;
  target: number | Node;
  type: string;
  strength: number;
}

interface DependencyGraphProps {
  modelId: number;
}

interface GraphData {
  nodes: Node[];
  edges: Edge[];
}

// D3 节点类型扩展
interface D3Node extends d3.SimulationNodeDatum {
  id: number;
  label: string;
  type: string;
}

interface D3Link extends d3.SimulationLinkDatum<D3Node> {
  source: D3Node;
  target: D3Node;
  type: string;
  strength: number;
}

const DependencyGraph: React.FC<DependencyGraphProps> = ({ modelId }) => {
  const [data, setData] = useState<GraphData>({ nodes: [], edges: [] });
  
  useEffect(() => {
          fetch(`/training_model_modelview/api/action/view_dependency_graph/${modelId}`)
      .then(res => res.json())
      .then((responseData: GraphData) => setData(responseData))
      .catch(error => console.error('Error fetching dependency graph:', error));
  }, [modelId]);
  
  useEffect(() => {
    if (data.nodes.length === 0) return;
    
    // 清除之前的 SVG
    d3.select('#dependency-graph').selectAll('*').remove();
    
    // D3.js 图形渲染逻辑
    const svg = d3.select('#dependency-graph')
      .append('svg')
      .attr('width', 800)
      .attr('height', 600);
    
    // 转换数据类型
    const nodes: D3Node[] = data.nodes.map(node => ({
      ...node,
      x: undefined,
      y: undefined
    }));
    
    const links: D3Link[] = data.edges.map(edge => ({
      source: nodes.find(n => n.id === (typeof edge.source === 'number' ? edge.source : edge.source.id))!,
      target: nodes.find(n => n.id === (typeof edge.target === 'number' ? edge.target : edge.target.id))!,
      type: edge.type,
      strength: edge.strength
    }));
    
    const simulation = d3.forceSimulation(nodes)
      .force('link', d3.forceLink<D3Node, D3Link>(links).id((d: D3Node) => d.id.toString()))
      .force('charge', d3.forceManyBody().strength(-300))
      .force('center', d3.forceCenter(400, 300));
    
    // 绘制边
    const linkElements = svg.selectAll('.link')
      .data(links)
      .enter().append('line')
      .attr('class', 'link')
      .style('stroke', '#999')
      .style('stroke-width', (d: D3Link) => d.strength * 2);
    
    // 绘制节点
    const nodeElements = svg.selectAll('.node')
      .data(nodes)
      .enter().append('circle')
      .attr('class', 'node')
      .attr('r', 20)
      .style('fill', (d: D3Node) => d.type === 'base' ? '#1f77b4' : '#ff7f0e')
      .style('cursor', 'pointer');
    
    // 添加标签
    const labelElements = svg.selectAll('.label')
      .data(nodes)
      .enter().append('text')
      .attr('class', 'label')
      .text((d: D3Node) => d.label)
      .style('text-anchor', 'middle')
      .style('font-size', '12px')
      .style('fill', '#333');
    
    // 添加拖拽功能
    const drag = d3.drag<SVGCircleElement, D3Node>()
      .on('start', (event, d: D3Node) => {
        if (!event.active) simulation.alphaTarget(0.3).restart();
        d.fx = d.x;
        d.fy = d.y;
      })
      .on('drag', (event, d: D3Node) => {
        d.fx = event.x;
        d.fy = event.y;
      })
      .on('end', (event, d: D3Node) => {
        if (!event.active) simulation.alphaTarget(0);
        d.fx = null;
        d.fy = null;
      });
    
    nodeElements.call(drag);
    
    simulation.on('tick', () => {
      linkElements
        .attr('x1', (d: D3Link) => (d.source as D3Node).x || 0)
        .attr('y1', (d: D3Link) => (d.source as D3Node).y || 0)
        .attr('x2', (d: D3Link) => (d.target as D3Node).x || 0)
        .attr('y2', (d: D3Link) => (d.target as D3Node).y || 0);
      
      nodeElements
        .attr('cx', (d: D3Node) => d.x || 0)
        .attr('cy', (d: D3Node) => d.y || 0);
      
      labelElements
        .attr('x', (d: D3Node) => d.x || 0)
        .attr('y', (d: D3Node) => (d.y || 0) + 5);
    });
    
    // 清理函数
    return () => {
      simulation.stop();
    };
    
  }, [data]);
  
  return (
    <div>
      <h3>模型依赖关系图</h3>
      <div id="dependency-graph" style={{ border: '1px solid #ccc', borderRadius: '4px' }}></div>
    </div>
  );
};

export default DependencyGraph;
